Skip to main content

테스트

발전된 테스트 피라미드

단위 테스팅

테스트 그룹 묶기

describe 함수를 이용하여 테스트 그룹을 묶을 수 있다.
  • 테스트를 묶어서 가독성이 향상되면, 어떤 기능을 검증하고자 하는지 이해하는데 크게 도움이 된다.
  • describe 블록을 중첩하여, 테스트 스위트를 구조화할 수 있다.
테스트 스위트(Suite)란?테스트 케이스의 집합

리액트 컴포넌트 테스트

Jest 단독으로도 리액트 애플리케이션을 테스트 할 수 있지만, 리액트 테스팅 라이브러리(React Testing Libraray)와 같은 전용 라이브러리를 사용하는 것보다 코드가 번잡해질 수 있다.
리액트 테스팅 라이브러리 (React Testing Libraray)
  • 리액트 컴포넌트 테스팅을 위한 강력한 경량 라이브러리
  • Jest 기반으로 리액트 컴포넌트를 손쉽게 다루는 유틸리티 함수가 추가됨
  • 테스트 코드를 사용자의 소프트웨어 사용 행태와 유사하게 작성하기를 권장
    (→ 세부 구현에 대한 것이 아닌 기능에 대한 테스트를 하는 것)
import React from "react";
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";

import { Section } from "../component/Section";

describe("Section", () => {
  it("renders a section with heading and content", () => {
    render(<Section heading="Basic" content="Hello world" />);

    expect(screen.getByText("Basic")).toBeInTheDocument();
    expect(screen.getByText("Hello world")).toBeInTheDocument();
  });
});

통합 테스트

통합 테스트는 여러 단위 코드들 사이의 상호작용에 대해 검증한다.
통합 테스트에서 상호작용이란?
  • 컴포넌트 간의 상호작용
  • 서버와 클라이언트의 상호작용
통합 테스트의 목적은 시스템의 각기 다른 부분들을 통합하면서 생길 수 있는 문제들을 발견하는 것
  • UI 컴포넌트 레벨에서의 통합 테스트:
    2개의 개별 컴포넌트 사이의 상호작용을 테스트해서 함께 올바르게 동작하는지 확인
  • 프론트엔드 코드와 백엔드 서비스가 자연스럽게 연결되는지 확인하고자 한다면?:
    애플리케이션의 다른 계층들이 함께 올바르게 동작하는지 보는 것이기 때문에, 이것 역시 통합 테스트

실제 테스트 구현 예제

법적인 정보를 담고 있는 긴 텍스트와 사용자 동의 여부를 표시하는 체크 박스가 있다.
  1. [Next] 버튼은 처음에 비활성화 버튼이다.
  2. 사용자가 동의 체크 박스를 체크하면, [Next] 버튼은 활성화되어 다음으로 넘어갈 수 있다.
import React from "react";
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
import { TermsAndConditions } from "../component/TermsAndConditions";
import userEvent from "@testing-library/user-event";

describe("Terms and Conditions", () => {
  it("Enables the next button upon accepting terms and conditions", async () => {
    render(<TermsAndConditions />);
    const button = screen.getByText("Next");
    expect(button).toBeDisabled();

    const checkbox = screen.getByRole("checkbox");

    await userEvent.click(checkbox);

    expect(button).toBeEnabled();
  });
});
  1. describe 함수는 TermsAndConditions 컴포넌트와 관련된 모든 테스트들을 테스트 스위트라는 그룹으로 묶는다.
  2. 테스트 스위트 안에는 it으로 표시한 단일 테스트 케이스가 있다.
    • Enables the next button upon accepting terms and conditions
      (이용약관과 조건에 동의하면 [NEXT] 버튼을 활성화하기) 설명이 적힌 테스트가 있다.
  3. 초기에는 TermsAndConditions 컴포넌트를 표시하기 위해 render 함수를 호출한다.
    • render함수는 컴포넌트가 예상대로 동작하는지 평가하기 위해, 다양한 방법으로 조회할 수 있는 일련의 출력이나, 렌더링 결과물을 생성한다.
  4. screen.getByText 함수를 이용하여, 페이지 안에서 검색한 요소를 반환받을 수 있다.
    • 이를 이용하여, [Next]라는 텍스트를 통해 버튼을 찾는다.
  5. expect(button).toBeDisabled()를 통해 찾은 버튼 요소가 비활성화 상태인지 확인할 수 있다.
  6. screen.getByRole 함수를 통해, 체크박스를 checkbox라는 역할로 요소를 찾을 수 있다.
  7. act 함수로 userEvent.click 함수를 통해, 사용자의 클릭 이벤트를 시뮬레이션 할 수 있다.
    • act 함수는 동작으로 인한 모든 UI 업데이트가 완료될 때가지 기다린 후에 다음 단계로 넘어간다.
    • 따라서, 테스트 과정에서 업데이트 된 상태를 정확하게 확인할 수 있따.
  8. expect(button).toBeEnabled()를 통해 체크박스를 클릭한 후 버튼이 활성화 되는 것을 확인할 수 있다.
실제 구현된 컴포넌트를 보면 아래와 같다.
//... 다른 내부 컴포넌트 구현
const TermsAndConditions = () => {
  return (
    <div>
      <h2>Terms and Conditions</h2>
      <TheLegalContent />
      <UserConsent />
    </div>
  );
};
export { TermsAndConditions };
실제 외부로 노출되는 컴포넌트는 TermsAndCondtions 하나 이다. 그리고 테스트에서 jsdom 환경에서 클릭 이벤트를 시작하기 위해 userEvent.click을 사용한다.
중요한 것은 개별 리액트 컴포넌트에 대한 단위 테스트를 수행하는 것이 아니라, DOM 요소간의 상호 작용에 초점을 맞추는 것
→ 이를 위해, 브라우저를 사용하지 않고, 유사한 모든 기능을 지원하는 jsdom을 사용한다.
jsdom은 메모리 위에서 동작하는 헤드리스 브라우저이다.
jsdom은 자바스크립트 기반의 헤드리스 브라우저이다.
실제 웹 브라우저와 유사한 테스팅 환경을 만들 때 사용한다. 자바스크립트로 HTML, DOM, CSS와 같은 웹 표준을 구현한다.
브라우저는 DOM을 제공하지만, Node.js 환경에서 jest와 같은 프레임워크를 사용할 때는 DOM을 기본적으로 제공하지 않는다.
  • jsdom은 가상의 DOM을 제공하기 때문에, 테스트가 Node.js 환경에서 실행되더라도 브라우저와 유사한 환경을 만들어준다.
  • jsdom은 브라우저를 띄우지 않고도 DOM과의 상호작용을 묘사할 수 있다.
AI 답변‘Headless’ 1 2는 ‘머리가 없는’이라는 뜻으로, UI(사용자 인터페이스)를 직접 제어하지 않는 상태를 의미합니다.
이는 주로 소프트웨어 개발 분야에서 기능(로직)과 화면(UI)을 분리한 구조나, GUI 없이 동작하는 시스템을 가리킬 때 사용됩니다.